package com.jzo2o.health.handler;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.jzo2o.api.trade.RefundRecordApi;
import com.jzo2o.api.trade.dto.response.ExecutionResultResDTO;
import com.jzo2o.common.utils.ObjectUtils;
import com.jzo2o.health.enums.OrderPayStatusEnum;
import com.jzo2o.health.enums.OrderStatusEnum;
import com.jzo2o.health.mapper.OrdersMapper;
import com.jzo2o.health.model.domain.Orders;
import com.jzo2o.health.model.domain.OrdersRefund;
import com.jzo2o.health.properties.OrdersJobProperties;
import com.jzo2o.health.service.IOrdersRefundService;
import com.jzo2o.health.service.IOrdersService;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * 订单相关定时任务
 *
 * @author itcast
 * @create 2023/9/2 16:44
 **/
@Slf4j
@Component
public class OrdersHandler {

    @Resource
    private RefundRecordApi refundRecordApi;
    //解决同级方法调用，事务失效问题
    @Resource
    private OrdersHandler orderHandler;
    @Resource
    private OrdersJobProperties ordersJobProperties;

    @Resource
    private IOrdersService ordersService;

    @Resource
    private IOrdersRefundService ordersRefundService;
    @Resource
    private OrdersMapper ordersMapper;


    /**
     * 支付超时取消订单
     * 每分钟执行一次
     */
    @XxlJob(value = "cancelOverTimePayOrder")
    public void cancelOverTimePayOrder() {
        // 查询所有未支付状态的订单，并且这些订单是在当前时间15分钟前创建的
        List<Orders> list = ordersService.lambdaQuery()
                .eq(Orders::getOrderStatus, OrderStatusEnum.NO_PAY)
                .eq(Orders::getPayStatus, OrderPayStatusEnum.NO_PAY)
                .gt(Orders::getCreateTime, LocalDateTime.now().minusMinutes(15))
                .last("limit 100")
                .list();

        // 遍历查询到的订单列表，对每个订单执行取消操作
        for (Orders orders : list) {
            // 调用取消订单的方法，传入订单ID，取消原因，以及是否为系统自动触发
            ordersService.cancelOrderByNoPay(orders.getId(), "订单超时未支付,已取消", true);
        }
    }

    /**
     * 订单退款异步任务
     */
    @XxlJob(value = "handleRefundOrders")
    public void handleRefundOrders() {
        List<OrdersRefund> list = ordersRefundService.lambdaQuery()
                .orderByAsc(OrdersRefund::getCreateTime)
                .last("limit 100")
                .list();

        for (OrdersRefund ordersRefund : list) {
            requestRefundOrder(ordersRefund);
        }
    }

    /**
     * 订单退款处理
     *
     * @param id                    订单id
     * @param executionResultResDTO 第三方退款信息
     */
    @Transactional(rollbackFor = Exception.class)
    public void refundOrder(Long id, ExecutionResultResDTO executionResultResDTO) {
        //退款到账但是executionResultResDTO返回的状态仍然是退款中 导致记录表始终不能删除
        Integer refundingStatus = OrderPayStatusEnum.REFUNDING.getStatus();
        if (Objects.equals(executionResultResDTO.getRefundStatus(), OrderPayStatusEnum.REFUND_SUCCESS.getStatus())) {
            // 退款成功
            refundingStatus = OrderPayStatusEnum.REFUND_SUCCESS.getStatus();
        } else if (Objects.equals(executionResultResDTO.getRefundStatus(), OrderPayStatusEnum.REFUND_FAIL.getStatus())) {
            // 退款失败
            refundingStatus = OrderPayStatusEnum.REFUND_FAIL.getStatus();
        }
        // 如果是退款中状态 程序结束等待下次定时
        if (Objects.equals(refundingStatus, OrderPayStatusEnum.REFUNDING.getStatus())) {
            return;
        }
        // 如果是非退款中 更新订单字段：refund_no refund_id
        LambdaUpdateWrapper<Orders> updateWrapper = new LambdaUpdateWrapper<Orders>()
                .eq(Orders::getId, id)
                .ne(Orders::getPayStatus, refundingStatus)
                .set(Orders::getPayStatus, refundingStatus)
                .set(ObjectUtil.isNotEmpty(executionResultResDTO.getRefundId()), Orders::getRefundId, executionResultResDTO.getRefundId())
                .set(ObjectUtil.isNotEmpty(executionResultResDTO.getRefundNo()), Orders::getRefundNo, executionResultResDTO.getRefundNo());
        int update = ordersMapper.update(null, updateWrapper);
        if (update > 0) {
            // 退款成功后删除退款记录
            ordersRefundService.removeById(id);
        }
    }

    public void requestRefundNewThread(Long ordersRefundId) {
        // 启动一个新线程请求退款
        new Thread(() -> {
            // 查询退款记录
            OrdersRefund ordersRefund = ordersRefundService.getById(ordersRefundId);
            if (ObjectUtils.isNotNull(ordersRefund)) {
                //请求退款
                requestRefundOrder(ordersRefund);
            }
        }).start();
    }

    /**
     * 请求退款订单
     *
     * 本方法负责调用第三方API进行订单退款，并在退款成功后处理订单的相关信息
     *
     * @param ordersRefund 包含退款订单信息的对象，包括交易订单号、实际支付金额等
     */
    public void requestRefundOrder(OrdersRefund ordersRefund) {
        // 调用第三方进行退款
        ExecutionResultResDTO executionResultResDTO = null;
        try {
            // 调用refundRecordApi的refundTrading方法进行退款操作
            executionResultResDTO = refundRecordApi.refundTrading(ordersRefund.getTradingOrderNo(), ordersRefund.getRealPayAmount());
        } catch (Exception e) {
            // 异常处理：打印异常信息
            e.printStackTrace();
        }
        // 检查退款操作是否成功
        if (executionResultResDTO != null) {
            // 退款后处理订单相关信息
            orderHandler.refundOrder(ordersRefund.getId(), executionResultResDTO);
        }
    }
}
